﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TibcoQueueMonitor.Entities;
using System.Xml;
using System.IO;
using System.Configuration;

namespace TibcoQueueMonitor.TibcoAdminManagers
{
    /// <summary>
    /// Manager object whose role is to retrieve configuration data from
    /// the various parts of the application.
    /// </summary>
    public static class TibcoAdminConfigurationManager
    {
        #region Constants
        private const string AttrProfileName = "name";
        private const string AttrHostname = "hostname";
        private const string AttrPort = "port";
        private const string AttrUser = "browseUser";
        private const string AttrPass = "browsePass";
        private const string AttrFriendlyName = "friendlyName";
        private const string AttrEnvironmentType = "environmentType";

        private const string xmlEmsServers = "EmsServers";
        private const string xmlServer = "Server";
        private const string xmlHosts = "Hosts";
        private const string xmlHost = "Host";

        private const string XmlFileExtension = ".xml";
        private const string FilenameEmsServ = "EmsServers.xml";
        private const string FilenameHosts = "Hosts.xml";
        private const string ConfigFolderName =  @"\TibcoEmsQueueMonitor\";
        private const string AppConfigDebugMode = "debugAdminDataMode";

        private const int defaultAutoRefreshInterval = 60;

        #endregion //Constants

        #region Public Methods
        /// <summary>
        /// Gets the debug mode flag.
        /// </summary>
        /// <returns></returns>
        public static bool GetDebugModeFlag()
        {
            bool offlineDebugAdminDataFlag = false;
            bool.TryParse(ConfigurationManager.AppSettings[AppConfigDebugMode], out offlineDebugAdminDataFlag);

            return offlineDebugAdminDataFlag;
        }

        /// <summary>
        /// Gets the auto refresh interval from the app.config file.
        /// </summary>
        /// <remarks>
        /// The minimum value is 5. If a value less than 5 is specified in the
        /// app.config, the method will return a value of 5 (seconds).
        /// </remarks>
        /// <returns>The number of seconds to elapse before the next
        /// refresh trigger.</returns>
        public static int GetAutoRefreshInterval()
        {
            string timeConfigString = ConfigurationManager.AppSettings["autoRefreshIntervalSec"];
            int seconds = defaultAutoRefreshInterval;

            if (!string.IsNullOrWhiteSpace(timeConfigString))
            {
                int.TryParse(timeConfigString, out seconds);
            }

            if (seconds < 5)
            {
                seconds = 5;
            }

            return seconds;
        }

        /// <summary>
        /// Gets the name of the offline data assembly.
        /// </summary>
        /// <returns></returns>
        public static string GetOfflineDataAssemblyName()
        {
            return ConfigurationManager.AppSettings["offlineDataGenerationAssemblyName"];
        }

        /// <summary>
        /// Gets the name of the offline data type.
        /// </summary>
        /// <returns></returns>
        public static string GetOfflineDataTypeName()
        {
            return ConfigurationManager.AppSettings["offlineDataGenerationTypeName"];
        }

        /// <summary>
        /// Gets the EMS server profiles from XML.
        /// </summary>
        /// <returns></returns>
        public static Dictionary<string, EmsServerProfile> GetEmsServerProfiles()
        {
            Dictionary<string, EmsServerProfile> serverIndex = new Dictionary<string, EmsServerProfile>();

            XmlDocument serverConfig = new XmlDocument();
            string emsFilename = String.Concat(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
               ConfigFolderName,
               FilenameEmsServ);

            if (File.Exists(emsFilename))
            {
                serverConfig.Load(emsFilename);

                XmlNodeList emsServers = serverConfig.SelectNodes(String.Concat("/", xmlEmsServers, "/", xmlServer));

                foreach (XmlNode node in emsServers)
                {
                    EmsServerProfile profileItem = new EmsServerProfile();

                    profileItem.ProfileName = node.Attributes[AttrProfileName].Value;
                    profileItem.Hostname = node.Attributes[AttrHostname].Value;
                    profileItem.Port = node.Attributes[AttrPort].Value;
                    profileItem.User = node.Attributes[AttrUser].Value;
                    profileItem.Password = node.Attributes[AttrPass].Value;

                    serverIndex.Add(profileItem.ProfileName, profileItem);
                }
            }

            return serverIndex;
        }

        /// <summary>
        /// Gets the hosts from XML.
        /// </summary>
        /// <returns></returns>
        public static Dictionary<string, ClientHost> GetHosts()
        {
            Dictionary<string, ClientHost> hostsIndex = new Dictionary<string, ClientHost>();

            XmlDocument hostsConfig = new XmlDocument();
            string hostsFilename = String.Concat(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
               ConfigFolderName,
               FilenameHosts);

            if (File.Exists(hostsFilename))
            {
                hostsConfig.Load(hostsFilename);

                XmlNodeList hosts = hostsConfig.SelectNodes("/Hosts/Host");

                foreach (XmlNode node in hosts)
                {
                    ClientHost hostItem = new ClientHost();

                    hostItem.FriendlyName = node.Attributes[AttrFriendlyName].Value;
                    hostItem.Hostname = node.Attributes[AttrHostname].Value;
                    hostItem.EnvironmentType = node.Attributes[AttrEnvironmentType].Value;

                    hostsIndex.Add(hostItem.Hostname, hostItem);
                }
            }

            return hostsIndex;
        }

        /// <summary>
        /// Saves the EMS server profiles to XML.
        /// </summary>
        /// <param name="serverProfiles">The server profiles.</param>
        public static void SaveEmsServerProfiles(ICollection<EmsServerProfile> serverProfiles)
        {
            //// Construct temp XML file
            string emsConfigFolder = String.Concat(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
                ConfigFolderName);
            string emsFilename = String.Concat(emsConfigFolder, FilenameEmsServ);

            string tempFileName = String.Concat(Guid.NewGuid().ToString(), XmlFileExtension);
            using (FileStream tempFs = File.Create(tempFileName))
            {
                XmlWriterSettings writerSettings = new XmlWriterSettings();
                writerSettings.Encoding = Encoding.UTF8;
                writerSettings.Indent = true;

                XmlWriter writer = XmlWriter.Create(tempFs, writerSettings);

                // Write XML declaration
                writer.WriteStartDocument();

                // Write Root: EmsServers
                writer.WriteStartElement(xmlEmsServers);

                // Write Server Nodes in EmsServers
                foreach (EmsServerProfile profile in serverProfiles)
                {
                    writer.WriteStartElement(xmlServer);
                    WriteAttribute(ref writer, AttrProfileName, profile.ProfileName);
                    WriteAttribute(ref writer, AttrHostname, profile.Hostname);
                    WriteAttribute(ref writer, AttrPort, profile.Port);
                    WriteAttribute(ref writer, AttrUser, profile.User);
                    WriteAttribute(ref writer, AttrPass, profile.Password);
                    writer.WriteEndElement();
                }

                // Write Closing Tags
                writer.WriteEndDocument();

                // Flush writer
                writer.Flush();
            }


            if (File.Exists(emsFilename))
            {
                //// Delete current XML file
                File.Delete(emsFilename);
            }

            if (!Directory.Exists(emsConfigFolder))
            {
                Directory.CreateDirectory(emsConfigFolder);
            }

            //// Rename temp XML file to EmsServers.xml
            File.Move(tempFileName, emsFilename);
        }

        /// <summary>
        /// Creates the hosts file.
        /// </summary>
        public static void CreateHostsFile()
        {
            string hostsConfigFolder = String.Concat(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
                ConfigFolderName);
            string hostsFilename = String.Concat(hostsConfigFolder, FilenameHosts);

            if (!File.Exists(hostsFilename))
            {
                // Create placeholder hosts collection
                ClientHost placeholderHost = new ClientHost();
                placeholderHost.EnvironmentType = "EMS Client";
                placeholderHost.FriendlyName = "EMS Test Client";
                placeholderHost.Hostname = "emsclient.tempuri.org";
                List<ClientHost> hosts = new List<ClientHost>();
                hosts.Add(placeholderHost);

                // Write hosts collection to file
                using (FileStream tempFs = File.Create(hostsFilename))
                {
                    XmlWriterSettings writerSettings = new XmlWriterSettings();
                    writerSettings.Encoding = Encoding.UTF8;
                    writerSettings.Indent = true;

                    XmlWriter writer = XmlWriter.Create(tempFs, writerSettings);

                    // Write XML declaration
                    writer.WriteStartDocument();

                    // Write Root: EmsServers
                    writer.WriteStartElement(xmlHosts);

                    // Write Server Nodes in Hosts
                    foreach (ClientHost host in hosts)
                    {
                        writer.WriteStartElement(xmlServer);
                        WriteAttribute(ref writer, AttrEnvironmentType, host.EnvironmentType);
                        WriteAttribute(ref writer, AttrFriendlyName, host.FriendlyName);
                        WriteAttribute(ref writer, AttrHostname, host.Hostname);
                        writer.WriteEndElement();
                    }

                    // Write Closing Tags
                    writer.WriteEndDocument();

                    // Flush writer
                    writer.Flush();
                }
            }
        }

        #endregion //Public Methods

        #region Private Methods
        private static void WriteAttribute(ref XmlWriter writer, string attrName, string value)
        {
            writer.WriteStartAttribute(attrName);
            writer.WriteValue(value);
            writer.WriteEndAttribute();
        }

        #endregion //Private Methods
    }
}
